package com.ourteam.product.model.api;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ourteam.frame.controller.AbstractServiceController;
import com.ourteam.frame.web.AbstractSearchHelper;
import com.ourteam.frame.web.GridBean;
import com.ourteam.frame.web.ProgressInfoBean;
import com.ourteam.frame.web.RequestStatus;
import com.ourteam.product.model.dao.ProductModelActionDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelCodeTemplateDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelObjectDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelObjectRelateDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelPropertyDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelPropertyRelateDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelServiceDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelServiceParameterDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelServiceTemplateDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelServiceTemplateItemDAOQueryBean;
import com.ourteam.product.model.domain.ProductModelActionBean;
import com.ourteam.product.model.domain.ProductModelCodeTemplateBean;
import com.ourteam.product.model.domain.ProductModelObjectBean;
import com.ourteam.product.model.domain.ProductModelObjectRelateBean;
import com.ourteam.product.model.domain.ProductModelPropertyBean;
import com.ourteam.product.model.domain.ProductModelPropertyRelateBean;
import com.ourteam.product.model.domain.ProductModelRelateTypeEnum;
import com.ourteam.product.model.domain.ProductModelServiceBean;
import com.ourteam.product.model.domain.ProductModelServiceParameterBean;
import com.ourteam.product.model.domain.ProductModelServiceParameterTemplateBean;
import com.ourteam.product.model.domain.ProductModelServiceParameterTypeEnum;
import com.ourteam.product.model.domain.ProductModelServiceTemplateBean;
import com.ourteam.product.model.domain.ProductModelServiceTemplateItemBean;
import com.ourteam.product.model.domain.ProductModelTypeEnum;
import com.ourteam.product.model.service.IProductModelService;
import com.ourteam.product.model.service.ProductModelServiceFactory;

import net.ui.UIConfigFactory;
import net.ui.model.form.FormBean;
import net.ui.model.form.FormPropertyBean;

@Controller
@CrossOrigin
@RequestMapping("/api/PRODUCT/MODEL/productModelObject")
public class ProductModelObjectAPI extends AbstractServiceController {

	private static final IProductModelService PRODUCT_MODEL_SERVICE = ProductModelServiceFactory
			.getProductModelService();

	@RequestMapping("/getModelObjectsByPackageId")
	@ResponseBody
	public ProductModelObjectBean[] getModelObjectsByPackageId(@RequestParam long packageId, HttpServletRequest request,
			Model model) throws Exception {

		ProductModelObjectDAOQueryBean queryBean = new ProductModelObjectDAOQueryBean();

		queryBean.createCriteria().andPackageIdEqualTo(packageId);

		ProductModelObjectBean[] objectBeans = PRODUCT_MODEL_SERVICE.queryProductModelObjects(queryBean);

		ModelObjectBean[] modelObjectBeans = new ModelObjectBean[objectBeans.length];

		for (int i = 0; i < objectBeans.length; i++) {

			modelObjectBeans[i] = new ModelObjectBean(objectBeans[i].convertToProductModelObject());

			modelObjectBeans[i]
					.setObjectProperties(PRODUCT_MODEL_SERVICE.getProductModelObjectProperties(objectBeans[i].getId()));
		}

		return modelObjectBeans;

	}

	@RequestMapping("/queryModelObjects")
	@ResponseBody
	public GridBean queryModelObjects(final @ModelAttribute ProductModelObjectSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelObjectDAOQueryBean, ProductModelObjectSearchModel> searchHelper = new AbstractSearchHelper<ProductModelObjectDAOQueryBean, ProductModelObjectSearchModel>(
				searchModel) {

			@Override
			protected ProductModelObjectDAOQueryBean createQueryBean() {
				return new ProductModelObjectDAOQueryBean();
			}

			@Override
			protected int queryCount(ProductModelObjectDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelObjectCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelObjectDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelObjects(queryBean);
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/queryModelObjectProperties")
	@ResponseBody
	public GridBean queryModelObjectProperties(final @ModelAttribute ProductModelPropertySearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelPropertyDAOQueryBean, ProductModelPropertySearchModel> searchHelper = new AbstractSearchHelper<ProductModelPropertyDAOQueryBean, ProductModelPropertySearchModel>(
				searchModel) {

			@Override
			protected ProductModelPropertyDAOQueryBean createQueryBean() {
				return new ProductModelPropertyDAOQueryBean();
			}

			@Override
			protected int queryCount(ProductModelPropertyDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelPropertyCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelPropertyDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelProperties(queryBean);
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/getModelPropertyByRelated")
	@ResponseBody
	public ProductModelPropertyRelateBean[] getModelPropertyByRelated(@RequestParam long propertyId,
			HttpServletRequest request, Model model) throws Exception {

		ProductModelPropertyRelateDAOQueryBean queryBean = new ProductModelPropertyRelateDAOQueryBean();

		queryBean.createCriteria().andRelatedPropertyIdEqualTo(propertyId);

		return PRODUCT_MODEL_SERVICE.queryProductModelPropertyRelates(queryBean);

	}

	@RequestMapping("/deleteModelProperties")
	@ResponseBody
	public boolean deleteModelProperties(@RequestParam(name = "ids") long[] propertyIds, HttpServletRequest request,
			Model model) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelProperties(propertyIds);

		return true;

	}

	@RequestMapping("/saveModelProperty")
	@ResponseBody
	public ProductModelPropertyBean saveModelProperty(@ModelAttribute ProductModelPropertyBean propertyBean,
			HttpServletRequest request, Model model) throws Exception {

		if (propertyBean.getId() == 0) {
			PRODUCT_MODEL_SERVICE.addNewProductModelProperty(propertyBean);
		} else {
			PRODUCT_MODEL_SERVICE.modifyProductModelProperty(propertyBean);
		}

		return propertyBean;

	}

	@RequestMapping("/deleteModelObject")
	@ResponseBody
	public boolean deleteModelObject(@RequestParam long objectId, HttpServletRequest request, Model model)
			throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelObjects(new long[] { objectId });

		return true;

	}

	@RequestMapping("/deleteModelObjects")
	@ResponseBody
	public boolean deleteModelObjects(@RequestParam(name = "ids") long[] objectIds, HttpServletRequest request,
			Model model) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelObjects(objectIds);

		return true;

	}

	@RequestMapping("/saveModelObject")
	@ResponseBody
	public ProductModelObjectBean saveModelObject(@ModelAttribute ProductModelObjectBean modelObjectBean,
			HttpServletRequest request, Model model) throws Exception {

		if (modelObjectBean.getId() != 0) {
			PRODUCT_MODEL_SERVICE.modifyProductModelObject(modelObjectBean);
		} else {
			PRODUCT_MODEL_SERVICE.addNewProductModelObject(modelObjectBean);
		}

		return modelObjectBean;
	}

	@RequestMapping("/queryModelObjectRelates")
	@ResponseBody
	public GridBean queryRelatedModelObjects(@ModelAttribute ProductModelObjectRelatedObjectSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelObjectRelateDAOQueryBean, ProductModelObjectRelatedObjectSearchModel> searchHelper = new AbstractSearchHelper<ProductModelObjectRelateDAOQueryBean, ProductModelObjectRelatedObjectSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(ProductModelObjectRelateDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelObjectRelateCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelObjectRelateDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelObjectRelates(queryBean);
			}

			@Override
			protected ProductModelObjectRelateDAOQueryBean createQueryBean() {
				ProductModelObjectRelateDAOQueryBean queryBean = new ProductModelObjectRelateDAOQueryBean();

				return queryBean;
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/getModelObjectRelates")
	@ResponseBody
	public ProductModelObjectRelateBean[] getModelObjectRelates(@RequestParam long relatedObjectId,
			@RequestParam String relatedType) throws Exception {

		ProductModelObjectRelateDAOQueryBean queryBean = new ProductModelObjectRelateDAOQueryBean();

		ProductModelObjectRelateDAOQueryBean.Criteria criteria = queryBean.createCriteria();

		criteria.andRelatedObjectIdEqualTo(relatedObjectId);

		if (StringUtils.isNotBlank(relatedType)) {
			String[] relatedTypes = StringUtils.split(relatedType, ",");
			if (ArrayUtils.isEmpty(relatedTypes)) {
				criteria.andRelatedTypeEqualTo(relatedType);
			} else {
				criteria.andRelatedTypeIn(relatedTypes);
			}

		}

		return PRODUCT_MODEL_SERVICE.queryProductModelObjectRelates(queryBean);

	}

	protected void processDaoImport(ProductModelObjectBean dao, ProductModelObjectBean table) throws Exception {

		long submitterId = getLoginUserId();

		dao.setSubmitterId(submitterId);

		Map<Object, String> dataTypeMap = UIConfigFactory.getInstance("product.databaseTableColumnDataTypeToJavaType")
				.getListDataConfigMap("product.databaseTableColumnDataTypeToJavaType");

		Map<String, String> customDataTypeMap = PRODUCT_MODEL_SERVICE.getProductDatabaseDataTypeMaps();

		Set<Object> keySet = dataTypeMap.keySet();

		for (Iterator<Object> iterator = keySet.iterator(); iterator.hasNext();) {
			Object key = iterator.next();
			if (customDataTypeMap.containsKey(key)) {
				dataTypeMap.put(key, customDataTypeMap.get(key));
			}
		}

		ProductModelPropertyBean[] propertyBeans = PRODUCT_MODEL_SERVICE.getProductPropertiesByObjectId(table.getId());

		String daoName = dao.getObjectName(); // convertDAOName(table.getObjectName());

		ProductModelObjectDAOQueryBean queryBean = new ProductModelObjectDAOQueryBean();

		queryBean.createCriteria().andPackageIdEqualTo(dao.getPackageId()).andObjectNameEqualTo(daoName)
				.andObjectTypeEqualTo(ProductModelTypeEnum.DAO.getName());

		ProductModelObjectBean[] modelObjectBeans = PRODUCT_MODEL_SERVICE.queryProductModelObjects(queryBean);

		if (ArrayUtils.isEmpty(modelObjectBeans)) {
			dao.setObjectType(ProductModelTypeEnum.DAO.getName());
			PRODUCT_MODEL_SERVICE.addNewProductModelObject(dao);

			ProductModelObjectBean daoQueryObject = new ProductModelObjectBean();

			daoQueryObject.setObjectType(ProductModelTypeEnum.QUERY_BEAN.getName());

			daoQueryObject.setSubmitterId(submitterId);

			daoQueryObject.setObjectName(daoName + "DAOQueryBean");

			daoQueryObject.setPackageId(dao.getPackageId());

			daoQueryObject.setIsGenerate("true");

			PRODUCT_MODEL_SERVICE.addNewProductModelObject(daoQueryObject);

			ProductModelObjectRelateBean modelObjectRelateBean = new ProductModelObjectRelateBean();

			modelObjectRelateBean.setObjectId(dao.getId());

			modelObjectRelateBean.setRelatedObjectId(table.getId());

			modelObjectRelateBean.setRelatedType(ProductModelRelateTypeEnum.MAP_TABLE.getName());

			PRODUCT_MODEL_SERVICE.addNewProductModelObjectRelate(modelObjectRelateBean);

			ProductModelObjectRelateBean modelDaoObjectRelateBean = new ProductModelObjectRelateBean();

			modelDaoObjectRelateBean.setObjectId(daoQueryObject.getId());

			modelDaoObjectRelateBean.setRelatedObjectId(dao.getId());

			modelDaoObjectRelateBean.setRelatedType(ProductModelRelateTypeEnum.DEPEND_DAO.getName());

			PRODUCT_MODEL_SERVICE.addNewProductModelObjectRelate(modelDaoObjectRelateBean);

			ProductModelPropertyRelateBean[] propertyRelateBeans = new ProductModelPropertyRelateBean[propertyBeans.length];

			for (int j = 0; j < propertyBeans.length; j++) {

				ProductModelPropertyBean column = propertyBeans[j];

				ProductModelPropertyBean property = new ProductModelPropertyBean();

				property.setSubmitterId(submitterId);

				property.setObjectId(dao.getId());

				property.setPropertyName(convertPropertyName(column.getPropertyName()));

				property.setRemarks(column.getRemarks());

				property.setSortIndex(j);

				property.setDataType(dataTypeMap.get(column.getDataType()));

				property.setDataLength(Integer.valueOf(column.getDataLength()));

				property.setDataAccuracy(Integer.valueOf(column.getDataAccuracy()));

				property.setDefaultValue(column.getDefaultValue());

				property.setIsAutoInc(column.getIsAutoInc());

				property.setIsAllowNull(column.getIsAllowNull());

				property.setIsPrimaryKey(column.getIsPrimaryKey());

				PRODUCT_MODEL_SERVICE.addNewProductModelProperty(property);

				ProductModelPropertyRelateBean propertyRelateBean = new ProductModelPropertyRelateBean();

				propertyRelateBean.setObjectRelateId(modelObjectRelateBean.getId());

				propertyRelateBean.setPropertyId(property.getId());

				propertyRelateBean.setRelatedPropertyId(column.getId());

				propertyRelateBean.setRelatedType(ProductModelRelateTypeEnum.MAP_TABLE.getName());

				propertyRelateBean.setSortIndex(j);

				propertyRelateBeans[j] = propertyRelateBean;

			}

			PRODUCT_MODEL_SERVICE.addNewProductModelPropertyRelates(propertyRelateBeans);

		}

	}

	@RequestMapping("/checkImportDaoObjectsJob")
	@ResponseBody
	public ProgressInfoBean checkImportDaoObjectsJob(@RequestParam long packageId, final HttpServletRequest request)
			throws Exception {

		return (ProgressInfoBean) request.getSession().getAttribute("importDaoObjects" + packageId);

	}

	@RequestMapping("/importDaoObjectsJob")
	@ResponseBody
	public RequestStatus importDaoObjectsJob(@RequestParam(name = "tableIds") long[] tableIds,
			@RequestParam final long packageId, final HttpServletRequest request) throws Exception {

		RequestStatus requestStatus = new RequestStatus();

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		progressInfoBean.setId("importDaoObjects" + packageId);

		progressInfoBean.setTask("导入DAO对象");

		progressInfoBean.setUnkownProgress(false);

		progressInfoBean.setProgressMessage("导入中，请稍候...");

		progressInfoBean.setTotalCount(tableIds.length);

		progressInfoBean.setValue(0);

		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		for (int i = 0; i < tableIds.length; i++) {
			final ProductModelObjectBean tableBean = PRODUCT_MODEL_SERVICE.getProductModelObjectById(tableIds[i]);

			ProductModelObjectBean daoObject = new ProductModelObjectBean();

			daoObject.setPackageId(packageId);

			daoObject.setObjectName(convertDAOName(tableBean.getObjectName()));

			daoObject.setIsGenerate("true");

			processDaoImport(daoObject, tableBean);

			progressInfoBean.setValue(i + 1);

			progressInfoBean.setProgressMessage("导入[" + daoObject.getObjectName() + "]");
		}

		requestStatus.setFinished(true);

		requestStatus.setSuccess(true);

		return requestStatus;
	}

	protected String convertDAOName(String name) {
		String[] strings = StringUtils.split(name, "_");

		StringBuffer nameBuffer = new StringBuffer();

		for (int i = 0; i < strings.length; i++) {
			String string = strings[i].toLowerCase();
			nameBuffer.append(StringUtils.capitalize(string));
		}

		return nameBuffer.toString();
	}

	protected String convertPropertyName(String name) {
		return StringUtils.uncapitalize(convertDAOName(name));
	}

	@RequestMapping("/queryRelatedModelProperties")
	@ResponseBody
	public GridBean queryRelatedModelProperties(@ModelAttribute ProductModelPropertyRelatedSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelPropertyRelateDAOQueryBean, ProductModelPropertyRelatedSearchModel> searchHelper = new AbstractSearchHelper<ProductModelPropertyRelateDAOQueryBean, ProductModelPropertyRelatedSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(ProductModelPropertyRelateDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelPropertyRelateCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelPropertyRelateDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelPropertyRelates(queryBean);
			}

			@Override
			protected ProductModelPropertyRelateDAOQueryBean createQueryBean() {
				return new ProductModelPropertyRelateDAOQueryBean();
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/getRelatedModelObjects")
	@ResponseBody
	public ProductModelObjectBean[] getRelatedModelObjects(@RequestParam long id, @RequestParam String relateType,
			HttpServletRequest request, Model model) throws Exception {

		String[] relateTypes = StringUtils.split(relateType, ",");

		ProductModelRelateTypeEnum[] typeEnums = new ProductModelRelateTypeEnum[relateTypes.length];

		for (int i = 0; i < relateTypes.length; i++) {
			typeEnums[i] = ProductModelRelateTypeEnum.getEnum(relateTypes[i]);
		}

		return PRODUCT_MODEL_SERVICE.getRelatedProductModelObjects(id, typeEnums);

	}

	@RequestMapping("/getRelatedModelObject")
	@ResponseBody
	public ProductModelObjectBean getRelatedModelObject(@RequestParam long id, @RequestParam String relateType,
			HttpServletRequest request, Model model) throws Exception {

		ProductModelObjectBean[] objectBeans = PRODUCT_MODEL_SERVICE.getRelatedProductModelObjects(id,
				new ProductModelRelateTypeEnum[] { ProductModelRelateTypeEnum.getEnum(relateType) });

		if (ArrayUtils.isNotEmpty(objectBeans)) {
			return objectBeans[0];
		} else {
			return null;
		}

	}

	@RequestMapping("/removeRelatedModelProperties")
	@ResponseBody
	public boolean removeRelatedModelProperties(@RequestParam(value = "ids") long[] ids, HttpServletRequest request,
			Model model) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelPropertyRelates(ids);

		return true;

	}

	@RequestMapping("/getNotRelatedProperties")
	@ResponseBody
	public ProductModelPropertyBean[] getNotRelatedProperties(@RequestParam long id, @RequestParam String relateType,
			HttpServletRequest request, Model model) throws Exception {

		String[] relateTypeArray = StringUtils.split(relateType, ",");

		ProductModelRelateTypeEnum[] relateTypeEnums = new ProductModelRelateTypeEnum[relateTypeArray.length];

		for (int i = 0; i < relateTypeEnums.length; i++) {
			relateTypeEnums[i] = ProductModelRelateTypeEnum.getEnum(relateTypeArray[i]);
		}

		return PRODUCT_MODEL_SERVICE.getProductModelNotRelatedPropertiesByType(id, relateTypeEnums);
	}

	@RequestMapping("/getModelObjectProperties")
	@ResponseBody
	public ProductModelPropertyBean[] getModelObjectProperties(@RequestParam long id, HttpServletRequest request,
			Model model) throws Exception {

		return PRODUCT_MODEL_SERVICE.getProductModelObjectProperties(id);

	}

	@RequestMapping("/addRelatedModelProperty")
	@ResponseBody
	public boolean addRelatedModelProperty(@ModelAttribute ProductModelPropertyRelateBean propertyRelateBean,
			HttpServletRequest request, Model model) throws Exception {

		PRODUCT_MODEL_SERVICE
				.addNewProductModelPropertyRelates(new ProductModelPropertyRelateBean[] { propertyRelateBean });

		return true;

	}

	@RequestMapping("/getModelObjectRelateId")
	@ResponseBody
	public long getModelObjectRelateId(@RequestParam long id, @RequestParam String relateType,
			HttpServletRequest request, Model model) throws Exception {

		ProductModelObjectRelateDAOQueryBean queryBean = new ProductModelObjectRelateDAOQueryBean();

		queryBean.createCriteria().andObjectIdEqualTo(id).andRelatedTypeEqualTo(relateType);

		ProductModelObjectRelateBean[] relateBeans = PRODUCT_MODEL_SERVICE.queryProductModelObjectRelates(queryBean);

		if (ArrayUtils.isNotEmpty(relateBeans)) {
			return relateBeans[0].getId();
		} else {
			return 0;
		}

	}

	@RequestMapping("/syncDaoObject")
	@ResponseBody
	public ProductModelObjectBean syncDaoObject(@RequestParam long daoId, final HttpServletRequest request)
			throws Exception {

		long submitterId = getLoginUserId();

		Map<Object, String> dataTypeMap = UIConfigFactory.getInstance("product.databaseTableColumnDataTypeToJavaType")
				.getListDataConfigMap("product.databaseTableColumnDataTypeToJavaType");

		Map<String, String> customDataTypeMap = PRODUCT_MODEL_SERVICE.getProductDatabaseDataTypeMaps();

		Set<Object> keySet = dataTypeMap.keySet();

		for (Iterator<Object> iterator = keySet.iterator(); iterator.hasNext();) {
			Object key = iterator.next();
			if (customDataTypeMap.containsKey(key)) {
				dataTypeMap.put(key, customDataTypeMap.get(key));
			}
		}

		final ProductModelObjectBean daoBean = PRODUCT_MODEL_SERVICE.getProductModelObjectById(daoId);

		ProductModelObjectBean[] mappedTables = PRODUCT_MODEL_SERVICE.getRelatedProductModelObjects(daoId,
				new ProductModelRelateTypeEnum[] { ProductModelRelateTypeEnum.MAP_TABLE });

		if (ArrayUtils.isNotEmpty(mappedTables)) {

			ProductModelObjectRelateDAOQueryBean relateDAOQueryBean = new ProductModelObjectRelateDAOQueryBean();

			relateDAOQueryBean.createCriteria().andObjectIdEqualTo(daoId)
					.andRelatedObjectIdEqualTo(mappedTables[0].getId())
					.andRelatedTypeEqualTo(ProductModelRelateTypeEnum.MAP_TABLE.getName());

			ProductModelObjectRelateBean[] modelObjectRelateBeans = PRODUCT_MODEL_SERVICE
					.queryProductModelObjectRelates(relateDAOQueryBean);

			ProductModelPropertyRelateDAOQueryBean queryBean = new ProductModelPropertyRelateDAOQueryBean();

			queryBean.createCriteria().andPropertyObjectIdEqualTo(daoId)
					.andRelatedPropertyObjectIdEqualTo(mappedTables[0].getId());

			ProductModelPropertyRelateBean[] propertyRelateBeans = PRODUCT_MODEL_SERVICE
					.queryProductModelPropertyRelates(queryBean);

			ProductModelPropertyBean[] propertyBeans = PRODUCT_MODEL_SERVICE
					.getProductModelObjectProperties(mappedTables[0].getId());

			ProductModelPropertyDAOQueryBean propertyDAOQueryBean = new ProductModelPropertyDAOQueryBean();

			propertyDAOQueryBean.createCriteria().andObjectIdEqualTo(daoId);

			int count = PRODUCT_MODEL_SERVICE.queryProductModelPropertyCount(propertyDAOQueryBean);

			List<ProductModelPropertyRelateBean> productModelPropertyRelateBeans = new ArrayList<>();

			for (int i = 0; i < propertyBeans.length; i++) {

				boolean founded = false;

				for (int j = 0; j < propertyRelateBeans.length; j++) {
					if (propertyRelateBeans[j].getRelatedPropertyId() == propertyBeans[i].getId()) {
						founded = true;
						break;
					}
				}

				if (founded == false) {

					ProductModelPropertyBean property = new ProductModelPropertyBean();

					property.setSubmitterId(submitterId);

					property.setObjectId(daoId);

					property.setPropertyName(convertPropertyName(propertyBeans[i].getPropertyName()));

					property.setRemarks(propertyBeans[i].getRemarks());

					property.setSortIndex(count + i + 1);

					property.setDataType(dataTypeMap.get(propertyBeans[i].getDataType()));

					property.setDataLength(Integer.valueOf(propertyBeans[i].getDataLength()));

					property.setDataAccuracy(Integer.valueOf(propertyBeans[i].getDataAccuracy()));

					property.setDefaultValue(propertyBeans[i].getDefaultValue());

					property.setIsAutoInc(propertyBeans[i].getIsAutoInc());

					property.setIsAllowNull(propertyBeans[i].getIsAllowNull());

					property.setIsPrimaryKey(propertyBeans[i].getIsPrimaryKey());

					PRODUCT_MODEL_SERVICE.addNewProductModelProperty(property);

					ProductModelPropertyRelateBean propertyRelateBean = new ProductModelPropertyRelateBean();

					propertyRelateBean.setObjectRelateId(modelObjectRelateBeans[0].getId());

					propertyRelateBean.setPropertyId(property.getId());

					propertyRelateBean.setRelatedPropertyId(propertyBeans[i].getId());

					propertyRelateBean.setRelatedType(ProductModelRelateTypeEnum.MAP_TABLE.getName());

					propertyRelateBean.setSortIndex(propertyRelateBeans.length + i);

					productModelPropertyRelateBeans.add(propertyRelateBean);
				}

			}

			PRODUCT_MODEL_SERVICE.addNewProductModelPropertyRelates(productModelPropertyRelateBeans
					.toArray(new ProductModelPropertyRelateBean[productModelPropertyRelateBeans.size()]));
		}

		return daoBean;
	}

	@RequestMapping("/syncDtoObject")
	@ResponseBody
	public ProductModelObjectBean syncDtoObject(@RequestParam long dtoId, final HttpServletRequest request)
			throws Exception {

		long submitterId = getLoginUserId();

		final ProductModelObjectBean dtoBean = PRODUCT_MODEL_SERVICE.getProductModelObjectById(dtoId);

		ProductModelObjectBean[] mappedDaos = PRODUCT_MODEL_SERVICE.getRelatedProductModelObjects(dtoId,
				new ProductModelRelateTypeEnum[] { ProductModelRelateTypeEnum.MAP_DAO });

		if (ArrayUtils.isNotEmpty(mappedDaos)) {

			ProductModelObjectRelateDAOQueryBean relateDAOQueryBean = new ProductModelObjectRelateDAOQueryBean();

			relateDAOQueryBean.createCriteria().andObjectIdEqualTo(dtoId)
					.andRelatedObjectIdEqualTo(mappedDaos[0].getId())
					.andRelatedTypeEqualTo(ProductModelRelateTypeEnum.MAP_DAO.getName());

			ProductModelObjectRelateBean[] modelObjectRelateBeans = PRODUCT_MODEL_SERVICE
					.queryProductModelObjectRelates(relateDAOQueryBean);

			ProductModelPropertyRelateDAOQueryBean queryBean = new ProductModelPropertyRelateDAOQueryBean();

			queryBean.createCriteria().andPropertyObjectIdEqualTo(dtoId)
					.andRelatedPropertyObjectIdEqualTo(mappedDaos[0].getId());

			ProductModelPropertyRelateBean[] propertyRelateBeans = PRODUCT_MODEL_SERVICE
					.queryProductModelPropertyRelates(queryBean);

			ProductModelPropertyBean[] propertyBeans = PRODUCT_MODEL_SERVICE
					.getProductModelObjectProperties(mappedDaos[0].getId());

			ProductModelPropertyDAOQueryBean propertyDAOQueryBean = new ProductModelPropertyDAOQueryBean();

			propertyDAOQueryBean.createCriteria().andObjectIdEqualTo(dtoId);

			int count = PRODUCT_MODEL_SERVICE.queryProductModelPropertyCount(propertyDAOQueryBean);

			List<ProductModelPropertyRelateBean> productModelPropertyRelateBeans = new ArrayList<>();

			for (int i = 0; i < propertyBeans.length; i++) {

				boolean founded = false;

				for (int j = 0; j < propertyRelateBeans.length; j++) {
					if (propertyRelateBeans[j].getRelatedPropertyId() == propertyBeans[i].getId()) {
						founded = true;
						break;
					}
				}

				if (founded == false) {

					ProductModelPropertyBean property = new ProductModelPropertyBean();

					property.setSubmitterId(submitterId);

					property.setObjectId(dtoId);

					property.setPropertyName(propertyBeans[i].getPropertyName());

					property.setRemarks(propertyBeans[i].getRemarks());

					property.setSortIndex(count + i + 1);

					property.setDataType(propertyBeans[i].getDataType());

					property.setDataLength(Integer.valueOf(propertyBeans[i].getDataLength()));

					property.setDataAccuracy(Integer.valueOf(propertyBeans[i].getDataAccuracy()));

					property.setDefaultValue(propertyBeans[i].getDefaultValue());

					property.setIsAutoInc(propertyBeans[i].getIsAutoInc());

					property.setIsAllowNull(propertyBeans[i].getIsAllowNull());

					property.setIsPrimaryKey(propertyBeans[i].getIsPrimaryKey());

					PRODUCT_MODEL_SERVICE.addNewProductModelProperty(property);

					ProductModelPropertyRelateBean propertyRelateBean = new ProductModelPropertyRelateBean();

					propertyRelateBean.setObjectRelateId(modelObjectRelateBeans[0].getId());

					propertyRelateBean.setPropertyId(property.getId());

					propertyRelateBean.setRelatedPropertyId(propertyBeans[i].getId());

					propertyRelateBean.setRelatedType(ProductModelRelateTypeEnum.MAP_DAO.getName());

					propertyRelateBean.setSortIndex(propertyRelateBeans.length + i);

					productModelPropertyRelateBeans.add(propertyRelateBean);
				}

			}

			PRODUCT_MODEL_SERVICE.addNewProductModelPropertyRelates(productModelPropertyRelateBeans
					.toArray(new ProductModelPropertyRelateBean[productModelPropertyRelateBeans.size()]));
		}

		return dtoBean;
	}

	@RequestMapping("/checkImportDtoObjectsJob")
	@ResponseBody
	public ProgressInfoBean checkImportDtoObjectsJob(@RequestParam long packageId, final HttpServletRequest request)
			throws Exception {

		return (ProgressInfoBean) request.getSession().getAttribute("importDtoObjects" + packageId);

	}

	@RequestMapping("/importDtoObjectsJob")
	@ResponseBody
	public RequestStatus importDtoObjectsJob(@RequestParam(name = "daoIds") long[] daoIds,
			@RequestParam final long packageId, final HttpServletRequest request) throws Exception {

		RequestStatus requestStatus = new RequestStatus();

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		progressInfoBean.setId("importDtoObjects" + packageId);

		progressInfoBean.setTask("导入DTO对象");

		progressInfoBean.setUnkownProgress(false);

		progressInfoBean.setProgressMessage("导入中，请稍候...");

		progressInfoBean.setTotalCount(daoIds.length);

		progressInfoBean.setValue(0);

		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		for (int i = 0; i < daoIds.length; i++) {
			final ProductModelObjectBean daoBean = PRODUCT_MODEL_SERVICE.getProductModelObjectById(daoIds[i]);

			ProductModelObjectBean dtoObject = new ProductModelObjectBean();

			dtoObject.setPackageId(packageId);

			dtoObject.setObjectName(daoBean.getObjectName() + "Bean");

			dtoObject.setIsGenerate("true");

			processDtoImport(dtoObject, daoBean);

			progressInfoBean.setValue(i + 1);

			progressInfoBean.setProgressMessage("导入[" + dtoObject.getObjectName() + "]");
		}

		requestStatus.setFinished(true);

		requestStatus.setSuccess(true);

		return requestStatus;
	}

	protected void processDtoImport(ProductModelObjectBean dtoObject, ProductModelObjectBean dao) throws Exception {

		long submitterId = getLoginUserId();

		dtoObject.setSubmitterId(submitterId);

		ProductModelPropertyBean[] propertyBeans = PRODUCT_MODEL_SERVICE.getProductPropertiesByObjectId(dao.getId());

		ProductModelObjectDAOQueryBean queryBean = new ProductModelObjectDAOQueryBean();

		queryBean.createCriteria().andPackageIdEqualTo(dtoObject.getPackageId())
				.andObjectNameEqualTo(dtoObject.getObjectName())
				.andObjectTypeEqualTo(ProductModelTypeEnum.DTO.getName());

		ProductModelObjectBean[] modelObjectBeans = PRODUCT_MODEL_SERVICE.queryProductModelObjects(queryBean);

		if (ArrayUtils.isEmpty(modelObjectBeans)) {

			dtoObject.setObjectType(ProductModelTypeEnum.DTO.getName());

			dtoObject.setIsGenerate("true");

			PRODUCT_MODEL_SERVICE.addNewProductModelObject(dtoObject);

			ProductModelObjectRelateBean modelObjectRelateBean = new ProductModelObjectRelateBean();

			modelObjectRelateBean.setObjectId(dtoObject.getId());

			modelObjectRelateBean.setRelatedObjectId(dao.getId());

			modelObjectRelateBean.setRelatedType(ProductModelRelateTypeEnum.MAP_DAO.getName());

			PRODUCT_MODEL_SERVICE.addNewProductModelObjectRelate(modelObjectRelateBean);

			ProductModelPropertyRelateBean[] propertyRelateBeans = new ProductModelPropertyRelateBean[propertyBeans.length];

			for (int j = 0; j < propertyBeans.length; j++) {

				ProductModelPropertyBean daoProperty = propertyBeans[j];

				ProductModelPropertyBean property = new ProductModelPropertyBean();

				property.setSubmitterId(submitterId);

				property.setObjectId(dtoObject.getId());

				property.setPropertyName(daoProperty.getPropertyName());

				property.setRemarks(daoProperty.getRemarks());

				property.setSortIndex(j);

				property.setDataType(daoProperty.getDataType());

				property.setDataLength(Integer.valueOf(daoProperty.getDataLength()));

				property.setDataAccuracy(Integer.valueOf(daoProperty.getDataAccuracy()));

				property.setDefaultValue(daoProperty.getDefaultValue());

				property.setIsAutoInc(daoProperty.getIsAutoInc());

				property.setIsAllowNull(daoProperty.getIsAllowNull());

				property.setIsPrimaryKey(daoProperty.getIsPrimaryKey());

				PRODUCT_MODEL_SERVICE.addNewProductModelProperty(property);

				ProductModelPropertyRelateBean propertyRelateBean = new ProductModelPropertyRelateBean();

				propertyRelateBean.setObjectRelateId(modelObjectRelateBean.getId());

				propertyRelateBean.setPropertyId(property.getId());

				propertyRelateBean.setRelatedPropertyId(daoProperty.getId());

				propertyRelateBean.setRelatedType(ProductModelRelateTypeEnum.MAP_DAO.getName());

				propertyRelateBean.setSortIndex(j);

				propertyRelateBeans[j] = propertyRelateBean;

			}

			PRODUCT_MODEL_SERVICE.addNewProductModelPropertyRelates(propertyRelateBeans);

		}

	}

	@RequestMapping("/setModelObjectRelationSort")
	@ResponseBody
	public boolean setModelObjectRelationSort(@RequestParam(value = "objectRelateIds") long[] objectRelateIds,
			HttpServletRequest request, Model model) throws Exception {

		PRODUCT_MODEL_SERVICE.setProductModelObjectRelateSort(objectRelateIds);

		return true;

	}

	@RequestMapping("/getModelObjectById")
	@ResponseBody
	public ProductModelObjectBean getModelObjectById(@RequestParam long id, HttpServletRequest request, Model model)
			throws Exception {

		return PRODUCT_MODEL_SERVICE.getProductModelObjectById(id);

	}

	@RequestMapping("/getModelPropertyById")
	@ResponseBody
	public ProductModelPropertyBean getModelPropertyById(@RequestParam long propertyId, HttpServletRequest request,
			Model model) throws Exception {
		return PRODUCT_MODEL_SERVICE.getProductModelPropertyById(propertyId);
	}

	@RequestMapping("/setProductModelObjectRelated")
	@ResponseBody
	public ProductModelObjectRelateBean setModelObjectRelated(
			@ModelAttribute ProductModelObjectRelateBean objectRelateBean, @RequestParam int keyPropertyLength,
			@RequestParam(value = "propertyIds") long[] propertyIds,
			@RequestParam(value = "relatedPropertyIds") long[] relatedPropertyIds, @RequestParam String relateType,
			HttpServletRequest request, Model model) throws Exception {

		List<ProductModelPropertyRelateBean> propertyRelateBeans = new ArrayList<ProductModelPropertyRelateBean>();

		objectRelateBean.setRelatedType(relateType);

		for (int i = 0; i < propertyIds.length; i++) {

			ProductModelPropertyRelateBean propertyRelateBean = new ProductModelPropertyRelateBean();

			propertyRelateBean.setPropertyId(propertyIds[i]);
			propertyRelateBean.setRelatedPropertyId(relatedPropertyIds[i]);
			propertyRelateBean.setRelatedType(relateType);

			if (i < keyPropertyLength) {
				propertyRelateBean.setRelatedConfig("RELATE_KEY");
			}

			propertyRelateBeans.add(propertyRelateBean);

		}

		PRODUCT_MODEL_SERVICE.setProductModelObjectRelated(objectRelateBean,
				propertyRelateBeans.toArray(new ProductModelPropertyRelateBean[propertyRelateBeans.size()]));

		return objectRelateBean;
	}

	@RequestMapping("/removeRelatedModelObjects")
	@ResponseBody
	public boolean removeRelatedModelObjects(@RequestParam(value = "ids") long[] ids, HttpServletRequest request,
			Model model) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelObjectRelates(ids);

		return true;

	}

	@RequestMapping("/getRelatedProperties")
	@ResponseBody
	public ProductModelPropertyRelateBean[] getRelatedModelProperties(
			@RequestParam(required = false, defaultValue = "0") long relationId, HttpServletRequest request,
			Model model) throws Exception {

		if (relationId == 0) {
			return new ProductModelPropertyRelateBean[0];
		}

		return PRODUCT_MODEL_SERVICE.getProductModelPropertyRelates(relationId);
	}

	@RequestMapping("/queryModelObjectActions")
	@ResponseBody
	public GridBean queryModelObjectActions(final @ModelAttribute ProductModelActionSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelActionDAOQueryBean, ProductModelActionSearchModel> searchHelper = new AbstractSearchHelper<ProductModelActionDAOQueryBean, ProductModelActionSearchModel>(
				searchModel) {

			@Override
			protected ProductModelActionDAOQueryBean createQueryBean() {
				return new ProductModelActionDAOQueryBean();
			}

			@Override
			protected int queryCount(ProductModelActionDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelActionCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelActionDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelActions(queryBean);
			}

		};

		return searchHelper.doSearch(request);
	}

	@RequestMapping("/getModelActionById")
	@ResponseBody
	public ProductModelActionBean getModelActionById(@RequestParam long actionId) throws Exception {
		return PRODUCT_MODEL_SERVICE.getProductModelActionById(actionId);
	}

	@RequestMapping("/saveModelAction")
	@ResponseBody
	public ProductModelActionBean saveModelAction(@ModelAttribute ProductModelActionBean modelActionBean)
			throws Exception {
		if (modelActionBean.getId() == 0) {
			PRODUCT_MODEL_SERVICE.addNewProductModelAction(modelActionBean);
		} else {
			PRODUCT_MODEL_SERVICE.modifyProductModelAction(modelActionBean);
		}

		return modelActionBean;
	}

	@RequestMapping("/deleteModelActions")
	@ResponseBody
	public boolean deleteModelActions(@RequestParam(name = "ids") long[] actionIds) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelActions(actionIds);

		return true;
	}

	@RequestMapping("/getModelRelatedPropertiesByType")
	@ResponseBody
	public ProductModelPropertyBean[] getModelRelatedPropertiesByType(@RequestParam long id,
			@RequestParam(required = false) String isPrimaryKey, @RequestParam String relateType,
			HttpServletRequest request, Model model) throws Exception {

		String[] relateTypes = StringUtils.split(relateType, ",");

		ProductModelRelateTypeEnum[] relateTypeEnums = new ProductModelRelateTypeEnum[relateTypes.length];

		for (int i = 0; i < relateTypeEnums.length; i++) {
			relateTypeEnums[i] = ProductModelRelateTypeEnum.getEnum(relateTypes[i]);
		}

		ProductModelPropertyBean[] propertyBeans = PRODUCT_MODEL_SERVICE.getProductModelRelatedPropertiesByType(id,
				relateTypeEnums);
		if (StringUtils.isBlank(isPrimaryKey)) {
			return propertyBeans;
		} else {
			List<ProductModelPropertyBean> beans = new ArrayList<ProductModelPropertyBean>();

			for (int i = 0; i < propertyBeans.length; i++) {
				ProductModelPropertyBean productModelPropertyBean = propertyBeans[i];
				if (productModelPropertyBean.getIsPrimaryKey().equals(isPrimaryKey)) {
					beans.add(productModelPropertyBean);
				}
			}

			return beans.toArray(new ProductModelPropertyBean[beans.size()]);
		}

	}

	@RequestMapping("/setModelObjectUnique")
	@ResponseBody
	public boolean setModelObjectUnique(@RequestParam long objectId,
			@RequestParam(value = "propertyIds", required = false) long[] propertyIds, HttpServletRequest request,
			Model model) throws Exception {

		ProductModelPropertyBean[] propertyBeans = PRODUCT_MODEL_SERVICE.getProductModelObjectProperties(objectId);

		for (int i = 0; i < propertyBeans.length; i++) {
			ProductModelPropertyBean productModelPropertyBean = propertyBeans[i];

			if (ArrayUtils.contains(propertyIds, productModelPropertyBean.getId())) {
				productModelPropertyBean.setIsUnique("true");
			} else {
				productModelPropertyBean.setIsUnique("false");
			}

			PRODUCT_MODEL_SERVICE.modifyProductModelProperty(productModelPropertyBean);

		}

		return true;

	}

	@RequestMapping("/queryModelCodeTemplateList")
	@ResponseBody
	public GridBean queryModelCodeTemplateList(@ModelAttribute ProductModelCodeTemplateSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelCodeTemplateDAOQueryBean, ProductModelCodeTemplateSearchModel> searchHelper = new AbstractSearchHelper<ProductModelCodeTemplateDAOQueryBean, ProductModelCodeTemplateSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(ProductModelCodeTemplateDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelCodeTemplateCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelCodeTemplateDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelCodeTemplates(queryBean);
			}

			@Override
			protected ProductModelCodeTemplateDAOQueryBean createQueryBean() {
				return new ProductModelCodeTemplateDAOQueryBean();
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/deleteModelCodeTemplate")
	@ResponseBody
	public boolean deleteModelCodeTemplate(@RequestParam(value = "ids") long[] ids) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelCodeTemplates(ids);

		return true;
	}

	@RequestMapping("/getModelCodeTemplateById")
	@ResponseBody
	public ProductModelCodeTemplateBean getModeCodeTemplateById(@RequestParam long id) throws Exception {

		return PRODUCT_MODEL_SERVICE.getProductModelCodeTemplateById(id);

	}

	@RequestMapping("/saveModelCodeTemplateConetnt")
	@ResponseBody
	public ProductModelCodeTemplateBean saveModelCodeTemplateConetnt(@RequestParam long id,
			@RequestParam String content) throws Exception {

		ProductModelCodeTemplateBean templateBean = PRODUCT_MODEL_SERVICE.getProductModelCodeTemplateById(id);

		templateBean.setFileContentTemplate(content);

		templateBean.setLastModifyTime(new Date());

		templateBean.setLastModifyUser(getLoginUserAccount());

		PRODUCT_MODEL_SERVICE.modifyProductModelCodeTemplate(templateBean);

		return templateBean;

	}

	@RequestMapping("/saveModelCodeTemplate")
	@ResponseBody
	public ProductModelCodeTemplateBean saveModelCodeTemplate(
			@ModelAttribute ProductModelCodeTemplateBean codeTemplateBean) throws Exception {

		codeTemplateBean.setLastModifyUser(getLoginUserName());

		if (codeTemplateBean.getId() == 0) {
			PRODUCT_MODEL_SERVICE.addNewProductModelCodeTemplate(codeTemplateBean);
		} else {
			PRODUCT_MODEL_SERVICE.modifyProductModelCodeTemplate(codeTemplateBean);
		}

		return codeTemplateBean;
	}

	@RequestMapping("/queryModelServiceTemplateList")
	@ResponseBody
	public GridBean queryModelServiceTemplateList(@ModelAttribute ProductModelServiceTemplateSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelServiceTemplateDAOQueryBean, ProductModelServiceTemplateSearchModel> searchHelper = new AbstractSearchHelper<ProductModelServiceTemplateDAOQueryBean, ProductModelServiceTemplateSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(ProductModelServiceTemplateDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelServiceTemplateCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelServiceTemplateDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelServiceTemplates(queryBean);
			}

			@Override
			protected ProductModelServiceTemplateDAOQueryBean createQueryBean() {
				return new ProductModelServiceTemplateDAOQueryBean();
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/deleteModelServiceTemplate")
	@ResponseBody
	public boolean deleteModelServiceTemplate(@RequestParam(value = "ids") long[] ids) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelServiceTemplates(ids);

		return true;
	}

	@RequestMapping("/getModelServiceTemplateById")
	@ResponseBody
	public ProductModelServiceTemplateBean getModeServiceTemplateById(@RequestParam long id) throws Exception {

		return PRODUCT_MODEL_SERVICE.getProductModelServiceTemplateById(id);

	}

	@RequestMapping("/saveModelServiceTemplate")
	@ResponseBody
	public ProductModelServiceTemplateBean saveModelServiceTemplate(
			@ModelAttribute ProductModelServiceTemplateBean dataTypeMapBean) throws Exception {

		if (dataTypeMapBean.getId() == 0) {
			PRODUCT_MODEL_SERVICE.addNewProductModelServiceTemplate(dataTypeMapBean);
		} else {
			PRODUCT_MODEL_SERVICE.modifyProductModelServiceTemplate(dataTypeMapBean);
		}

		return dataTypeMapBean;
	}

	@RequestMapping("/queryModelServiceList")
	@ResponseBody
	public GridBean queryModelServiceList(@ModelAttribute ProductModelServiceSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelServiceDAOQueryBean, ProductModelServiceSearchModel> searchHelper = new AbstractSearchHelper<ProductModelServiceDAOQueryBean, ProductModelServiceSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(ProductModelServiceDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelServiceCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelServiceDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelServices(queryBean);
			}

			@Override
			protected ProductModelServiceDAOQueryBean createQueryBean() {
				return new ProductModelServiceDAOQueryBean();
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/queryModelServiceTemplateItemList")
	@ResponseBody
	public GridBean queryModelServiceTemplateItemList(
			@ModelAttribute ProductModelServiceTemplateItemSearchModel searchModel, HttpServletRequest request,
			Model model) throws Exception {

		AbstractSearchHelper<ProductModelServiceTemplateItemDAOQueryBean, ProductModelServiceTemplateItemSearchModel> searchHelper = new AbstractSearchHelper<ProductModelServiceTemplateItemDAOQueryBean, ProductModelServiceTemplateItemSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(ProductModelServiceTemplateItemDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelServiceTemplateItemCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelServiceTemplateItemDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelServiceTemplateItems(queryBean);
			}

			@Override
			protected ProductModelServiceTemplateItemDAOQueryBean createQueryBean() {
				return new ProductModelServiceTemplateItemDAOQueryBean();
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/deleteModelServiceTemplateItem")
	@ResponseBody
	public boolean deleteModelServiceTemplateItem(@RequestParam(value = "ids") long[] ids) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelServiceTemplateItems(ids);

		return true;
	}

	@RequestMapping("/getModelServiceTemplateItemById")
	@ResponseBody
	public ProductModelServiceTemplateItemBean getModeServiceTemplateItemById(@RequestParam long id) throws Exception {

		return PRODUCT_MODEL_SERVICE.getProductModelServiceTemplateItemById(id);

	}

	@RequestMapping("/saveModelServiceTemplateItem")
	@ResponseBody
	public ProductModelServiceTemplateItemBean saveModelServiceTemplateItem(
			@ModelAttribute ProductModelServiceTemplateItemBean dataTypeMapBean) throws Exception {

		if (dataTypeMapBean.getId() == 0) {
			PRODUCT_MODEL_SERVICE.addNewProductModelServiceTemplateItem(dataTypeMapBean);
		} else {
			PRODUCT_MODEL_SERVICE.modifyProductModelServiceTemplateItem(dataTypeMapBean);
		}

		return dataTypeMapBean;
	}

	@RequestMapping("/setModelServiceTemplateItemParameter/{id}")
	@ResponseBody
	public boolean saveModelServiceTemplateItemParameter(@PathVariable("id") long id,
			@RequestBody ProductModelServiceParameterTemplateBean[] params) throws Exception {

		PRODUCT_MODEL_SERVICE.setProductModelServiceParameterTemplates(id, params);

		return true;
	}

	@RequestMapping("/getModelServiceTemplateItemParameters")
	@ResponseBody
	public ProductModelServiceParameterTemplateBean[] getModelServiceTemplateItemParameters(@RequestParam long id)
			throws Exception {

		return PRODUCT_MODEL_SERVICE.getProductModelServiceTemplateItemParameters(id);

	}

	@RequestMapping("/getModelServiceTemplateItemParameterById")
	@ResponseBody
	public ProductModelServiceParameterTemplateBean getModelServiceTemplateItemParameterById(@RequestParam long id)
			throws Exception {

		return null;

	}

	@RequestMapping("/genModelobjectCode")
	@ResponseBody
	public String genModelobjectCode(@RequestParam long id, @RequestParam long templateId) throws Exception {

		ProductModelObjectBean modelObjectBean = PRODUCT_MODEL_SERVICE.getProductModelObjectById(id);

		ProductModelCodeTemplateBean codeTemplateBean = PRODUCT_MODEL_SERVICE
				.getProductModelCodeTemplateById(templateId);

		String sourceCode = ProductModelCodeGenerator.generateProductModelObjectCode(modelObjectBean, codeTemplateBean,
				null)[1];

		return sourceCode;
	}

	@RequestMapping("/addModelObjectRelate")
	@ResponseBody
	public ProductModelObjectRelateBean addModelObjectRelate(@RequestParam long objectId,
			@RequestParam long mappedObjectId, @RequestParam String mapType, final HttpServletRequest request)
			throws Exception {

		ProductModelObjectRelateDAOQueryBean queryBean = new ProductModelObjectRelateDAOQueryBean();

		queryBean.createCriteria().andObjectIdEqualTo(objectId).andRelatedTypeEqualTo(mapType);

		ProductModelObjectRelateBean[] objectRelateBeans = PRODUCT_MODEL_SERVICE
				.queryProductModelObjectRelates(queryBean);

		if (ArrayUtils.isNotEmpty(objectRelateBeans)) {
			long[] productModelObjectRelateBeanIds = new long[objectRelateBeans.length];
			for (int i = 0; i < productModelObjectRelateBeanIds.length; i++) {
				productModelObjectRelateBeanIds[i] = objectRelateBeans[i].getId();
			}
			PRODUCT_MODEL_SERVICE.deleteProductModelObjectRelates(productModelObjectRelateBeanIds);
		}

		ProductModelObjectRelateBean productModelObjectRelateBean = new ProductModelObjectRelateBean();

		productModelObjectRelateBean.setObjectId(objectId);

		productModelObjectRelateBean.setRelatedObjectId(mappedObjectId);

		productModelObjectRelateBean.setRelatedType(mapType);

		PRODUCT_MODEL_SERVICE.addNewProductModelObjectRelate(productModelObjectRelateBean);

		return productModelObjectRelateBean;
	}

	@RequestMapping("/addModelObjectRelates")
	@ResponseBody
	public ProductModelObjectRelateBean[] addModelObjectRelates(@RequestParam long objectId,
			@RequestParam(value = "relatedObjectIds") long[] relatedObjectIds, @RequestParam String relatedType,
			final HttpServletRequest request) throws Exception {

		ProductModelObjectRelateBean[] relateBeans = new ProductModelObjectRelateBean[relatedObjectIds.length];

		for (int i = 0; i < relateBeans.length; i++) {
			relateBeans[i] = new ProductModelObjectRelateBean();
			relateBeans[i].setObjectId(objectId);

			relateBeans[i].setRelatedObjectId(relatedObjectIds[i]);

			relateBeans[i].setRelatedType(relatedType);

			PRODUCT_MODEL_SERVICE.addNewProductModelObjectRelate(relateBeans[i]);
		}

		return relateBeans;
	}

	@RequestMapping("/saveModelService")
	@ResponseBody
	public ProductModelServiceBean saveModelService(@ModelAttribute ProductModelServiceBean modelServiceBean)
			throws Exception {
		if (modelServiceBean.getId() == 0) {
			PRODUCT_MODEL_SERVICE.addNewProductModelService(modelServiceBean);
		} else {
			PRODUCT_MODEL_SERVICE.modifyProductModelService(modelServiceBean);
		}

		return modelServiceBean;
	}

	@RequestMapping("/deleteModelServices")
	@ResponseBody
	public boolean deleteModelServices(@RequestParam(name = "ids") long[] serviceIds) throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelServices(serviceIds);

		return true;
	}

	@RequestMapping("/saveServiceParameter")
	@ResponseBody
	public ProductModelServiceParameterBean saveServiceParameter(
			@ModelAttribute ProductModelServiceParameterBean parameterBean) throws Exception {

		if (parameterBean.getId() == 0) {
			PRODUCT_MODEL_SERVICE.addNewProductModelServiceParameter(parameterBean);
		} else {
			PRODUCT_MODEL_SERVICE.modifyProductModelServiceParameter(parameterBean);
		}

		return parameterBean;

	}

	@RequestMapping("/getServiceOutputParameter")
	@ResponseBody
	public ProductModelServiceParameterBean getServiceOutputParameter(@RequestParam long serviceId) throws Exception {

		ProductModelServiceParameterDAOQueryBean queryBean = new ProductModelServiceParameterDAOQueryBean();

		queryBean.createCriteria().andServiceIdEqualTo(serviceId).andParameterTypeEqualTo("OUTPUT");

		ProductModelServiceParameterBean[] parameterBeans = PRODUCT_MODEL_SERVICE
				.queryProductModelServiceParameters(queryBean);

		if (ArrayUtils.isNotEmpty(parameterBeans)) {
			return parameterBeans[0];
		} else {

			ProductModelServiceParameterBean parameterBean = new ProductModelServiceParameterBean();

			parameterBean.setDataTypeId(0);

			parameterBean.setServiceId(serviceId);

			parameterBean.setIsArray("false");

			parameterBean.setParameterType("OUTPUT");

			PRODUCT_MODEL_SERVICE.addNewProductModelServiceParameter(parameterBean);

			return parameterBean;

		}

	}

	@RequestMapping("/queryServiceParameters")
	@ResponseBody
	public GridBean queryServiceParameters(final @ModelAttribute ProductModelServiceParameterSearchBean searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<ProductModelServiceParameterDAOQueryBean, ProductModelServiceParameterSearchBean> searchHelper = new AbstractSearchHelper<ProductModelServiceParameterDAOQueryBean, ProductModelServiceParameterSearchBean>(
				searchModel) {

			@Override
			protected ProductModelServiceParameterDAOQueryBean createQueryBean() {
				return new ProductModelServiceParameterDAOQueryBean();
			}

			@Override
			protected int queryCount(ProductModelServiceParameterDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelServiceParameterCount(queryBean);
			}

			@Override
			protected Object[] queryData(ProductModelServiceParameterDAOQueryBean queryBean) throws Exception {
				return PRODUCT_MODEL_SERVICE.queryProductModelServiceParameters(queryBean);
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/deleteModelServiceParameters")
	@ResponseBody
	public boolean deleteModelServiceParameters(@RequestParam(value = "parameterIds") long[] parameterIds)
			throws Exception {

		PRODUCT_MODEL_SERVICE.deleteProductModelServiceParameters(parameterIds);

		return true;
	}

	@RequestMapping("/getServiceParameterById")
	@ResponseBody
	public ProductModelServiceParameterBean getServiceParameterById(@RequestParam long id) throws Exception {

		return PRODUCT_MODEL_SERVICE.getProductModelServiceParameterById(id);

	}

	@RequestMapping("/getModelDataTypes")
	@ResponseBody
	public ProductModelObjectBean[] getModelDataTypes() throws Exception {

		ProductModelObjectDAOQueryBean queryBean = new ProductModelObjectDAOQueryBean();

		queryBean.createCriteria().andObjectTypeEqualTo(ProductModelTypeEnum.DATA_TYPE.getName());

		return PRODUCT_MODEL_SERVICE.queryProductModelObjects(queryBean);

	}

	protected String evaluateTemplate(Map<String, Object> objectMap, String template) {

		if (template == null) {
			return "";
		}

		StringWriter writer = new StringWriter();

		new VelocityEngine().evaluate(new VelocityContext(objectMap), writer, "Service Template",
				new StringReader(template));

		return writer.toString();
	}

	@RequestMapping("/getModelServiceTemplateExpressionFormBean")
	@ResponseBody
	public FormBean getModelServiceTemplateExpressionFormBean(@RequestParam long serviceTemplateId) throws Exception {

		Map<String, Long> inputObjectMap = new HashMap<String, Long>();

		List<String> serviceMethodList = new ArrayList<String>();

		ProductModelServiceTemplateItemDAOQueryBean itemDAOQueryBean = new ProductModelServiceTemplateItemDAOQueryBean();

		itemDAOQueryBean.createCriteria().andServiceTemplateIdEqualTo(serviceTemplateId);

		ProductModelServiceTemplateItemBean[] templateItemBeans = PRODUCT_MODEL_SERVICE
				.queryProductModelServiceTemplateItems(itemDAOQueryBean);

		for (int i = 0; i < templateItemBeans.length; i++) {

			ProductModelServiceTemplateItemBean productModelServiceTemplateItemBean = templateItemBeans[i];

			StringBuffer serviceMethod = new StringBuffer();

			StringBuffer serviceMethodOutPut = new StringBuffer();

			StringBuffer serviceMethodInPut = new StringBuffer();

			String[] objects = getObjectExpression(productModelServiceTemplateItemBean.getServiceNameTemplate());

			for (int j = 0; j < objects.length; j++) {
				if (inputObjectMap.containsKey(objects[j]) == false) {
					inputObjectMap.put(objects[j], Long.valueOf(0));
				}
			}

			ProductModelServiceParameterTemplateBean[] parameterTemplateBeans = PRODUCT_MODEL_SERVICE
					.getProductModelServiceTemplateItemParameters(productModelServiceTemplateItemBean.getId());

			for (int j = 0; j < parameterTemplateBeans.length; j++) {

				ProductModelServiceParameterTemplateBean productModelServiceParameterTemplateBean = parameterTemplateBeans[j];

				if (ProductModelServiceParameterTypeEnum.OUTPUT.getName()
						.equals(productModelServiceParameterTemplateBean.getParameterType())) {

					if (productModelServiceParameterTemplateBean.getDataTypeId() != 0) {
						serviceMethodOutPut.append(PRODUCT_MODEL_SERVICE
								.getProductModelObjectById(productModelServiceParameterTemplateBean.getDataTypeId())
								.getObjectCode());
					} else if (StringUtils
							.isNotBlank(productModelServiceParameterTemplateBean.getDataTypeIdExpression())) {
						serviceMethodOutPut.append(productModelServiceParameterTemplateBean.getDataTypeIdExpression());
					} else {
						serviceMethodOutPut.append("void");
					}

					if (BooleanUtils.toBoolean(productModelServiceParameterTemplateBean.getIsArray())) {
						serviceMethodOutPut.append("[]");
					}

				} else {

					if (StringUtils.isNotBlank(serviceMethodInPut.toString())) {
						serviceMethodInPut.append(",");
					}

					if (productModelServiceParameterTemplateBean.getDataTypeId() != 0) {
						serviceMethodInPut.append(PRODUCT_MODEL_SERVICE
								.getProductModelObjectById(productModelServiceParameterTemplateBean.getDataTypeId())
								.getObjectCode());
					} else if (StringUtils
							.isNotBlank(productModelServiceParameterTemplateBean.getDataTypeIdExpression())) {
						serviceMethodInPut.append(productModelServiceParameterTemplateBean.getDataTypeIdExpression());
					}

					if (BooleanUtils.toBoolean(productModelServiceParameterTemplateBean.getIsArray())) {
						serviceMethodInPut.append("[]");
					}

					serviceMethodInPut.append(" ")
							.append(productModelServiceParameterTemplateBean.getParameterNameTemplate());
				}

				String[] dataTypeObjects = getObjectExpression(
						productModelServiceParameterTemplateBean.getDataTypeIdExpression());

				for (int k = 0; k < dataTypeObjects.length; k++) {
					if (inputObjectMap.containsKey(dataTypeObjects[k]) == false) {
						inputObjectMap.put(dataTypeObjects[k], Long.valueOf(0));
					}
				}

				String[] parameterNameObjects = getObjectExpression(
						productModelServiceParameterTemplateBean.getParameterNameTemplate());

				for (int k = 0; k < parameterNameObjects.length; k++) {
					if (inputObjectMap.containsKey(parameterNameObjects[k]) == false) {
						inputObjectMap.put(parameterNameObjects[k], Long.valueOf(0));
					}
				}
			}

			serviceMethod.append(serviceMethodOutPut).append(" ")
					.append(productModelServiceTemplateItemBean.getServiceNameTemplate()).append("(")
					.append(serviceMethodInPut).append(")");

			serviceMethodList.add(serviceMethod.toString());

		}

		FormBean formBean = new FormBean();

		Set<String> keySet = inputObjectMap.keySet();

		for (Iterator<String> iterator = keySet.iterator(); iterator.hasNext();) {
			String key = iterator.next();
			FormPropertyBean formPropertyBean = new FormPropertyBean();

			formPropertyBean.setId(key);

			formPropertyBean.setAllowNull(false);

			formPropertyBean.setTitle(key);

			formPropertyBean.setType("list");

			formBean.addFormProperty(formPropertyBean);
		}

		return formBean;

	}

	protected String[] getObjectExpression(String input) {

		if (input == null) {
			return ArrayUtils.EMPTY_STRING_ARRAY;
		}

		List<String> objectList = new ArrayList<String>();

		String[] strings = StringUtils.substringsBetween(input, "${", "}");

		for (int i = 0; strings != null && i < strings.length; i++) {
			String string = StringUtils.trim(strings[i]);

			if (StringUtils.isEmpty(string)) {
				continue;
			}

			String[] strs = StringUtils.split(string, ".");
			if (ArrayUtils.isNotEmpty(strs)) {
				objectList.add(strs[0]);
			}

		}

		return objectList.toArray(new String[objectList.size()]);
	}

	@RequestMapping("/addNewProductServiceByTemplate")
	@ResponseBody
	protected boolean addNewProductServiceByTemplate(@RequestParam long serviceId, @RequestParam long templateId,
			@RequestParam Map<String, String> inputObjectMap) throws Exception {

		ProductModelServiceTemplateBean serviceTemplateBean = PRODUCT_MODEL_SERVICE
				.getProductModelServiceTemplateById(templateId);

		Map<String, Object> objectMap = new HashMap<String, Object>();

		Set<String> keySet = inputObjectMap.keySet();

		for (Iterator<String> iterator = keySet.iterator(); iterator.hasNext();) {
			String key = iterator.next();
			if (inputObjectMap.get(key) != null && key.startsWith("inputObjectMap")
					&& StringUtils.isNumeric(inputObjectMap.get(key))) {
				objectMap.put(StringUtils.substringBetween(key, "[", "]"),
						PRODUCT_MODEL_SERVICE.getProductModelObjectById(Long.parseLong(inputObjectMap.get(key))));
			} else {
				objectMap.put(key, new Object());
			}
		}

		ProductModelServiceTemplateItemDAOQueryBean itemDAOQueryBean = new ProductModelServiceTemplateItemDAOQueryBean();

		itemDAOQueryBean.createCriteria().andServiceTemplateIdEqualTo(serviceTemplateBean.getId());

		ProductModelServiceTemplateItemBean[] templateItemBeans = PRODUCT_MODEL_SERVICE
				.queryProductModelServiceTemplateItems(itemDAOQueryBean);

		for (int i = 0; i < templateItemBeans.length; i++) {

			ProductModelServiceTemplateItemBean productModelServiceTemplateItemBean = templateItemBeans[i];

			ProductModelServiceBean productModelServiceBean = new ProductModelServiceBean();

			productModelServiceBean.setObjectId(serviceId);

			productModelServiceBean.setServiceName(
					evaluateTemplate(objectMap, productModelServiceTemplateItemBean.getServiceNameTemplate()));

			PRODUCT_MODEL_SERVICE.addNewProductModelService(productModelServiceBean);

			ProductModelServiceParameterTemplateBean[] parameterTemplateBeans = PRODUCT_MODEL_SERVICE
					.getProductModelServiceTemplateItemParameters(productModelServiceTemplateItemBean.getId());

			List<ProductModelServiceParameterBean> parameterBeans = new ArrayList<ProductModelServiceParameterBean>();

			for (int j = 0; j < parameterTemplateBeans.length; j++) {

				ProductModelServiceParameterTemplateBean productModelServiceParameterTemplateBean = parameterTemplateBeans[j];

				ProductModelServiceParameterBean parameterBean = new ProductModelServiceParameterBean();

				parameterBean.setParameterType(productModelServiceParameterTemplateBean.getParameterType());

				parameterBean.setIsArray(productModelServiceParameterTemplateBean.getIsArray());

				parameterBean.setDataCheck(productModelServiceParameterTemplateBean.getDataCheck());

				parameterBean.setSortIndex(productModelServiceParameterTemplateBean.getSortIndex());

				parameterBean.setParameterName(evaluateTemplate(objectMap,
						productModelServiceParameterTemplateBean.getParameterNameTemplate()));

				if (StringUtils.isNotBlank(productModelServiceParameterTemplateBean.getDataTypeIdExpression())) {

					String objectName = evaluateTemplate(objectMap,
							productModelServiceParameterTemplateBean.getDataTypeIdExpression());

					ProductModelObjectDAOQueryBean queryBean = new ProductModelObjectDAOQueryBean();

					queryBean.createCriteria().andObjectCodeEqualTo(objectName);

					ProductModelObjectBean[] objectBeans = PRODUCT_MODEL_SERVICE.queryProductModelObjects(queryBean);

					if (ArrayUtils.isNotEmpty(objectBeans)) {
						parameterBean.setDataTypeId(objectBeans[0].getId());
					}

				} else if (productModelServiceParameterTemplateBean.getDataTypeId() != 0) {
					parameterBean.setDataTypeId(productModelServiceParameterTemplateBean.getDataTypeId());
				}

				parameterBeans.add(parameterBean);

			}

			PRODUCT_MODEL_SERVICE.setProductModelServiceParameters(productModelServiceBean.getId(),
					parameterBeans.toArray(new ProductModelServiceParameterBean[parameterBeans.size()]));
		}

		return true;

	}

}
